#define  _CRT_SECURE_NO_WARNINGS 1
#include "Priority_Queue.hpp"
#include "Sort.h"
#include <vector>

//int main()
//{
//	lw::priority_queue<int, std::vector<int>, std::greater<int>> heap{ 1, 32, 43, 12, 10, 20 };
//	while (heap.size())
//	{
//		std::cout << heap.top() << " ";
//		heap.pop();
//	}
//
//	return 0;
//}

void Print(std::vector<int>& nums)
{
	for (const auto& e : nums)
		std::cout << e << "  ";
	std::cout << std::endl;
}
//
//int main()
//{
//	std::vector<int> nums = { 9, 1, 23, 43, 81, 77, 5, 19, 29 };
//	//HeapSort(nums);
//	QuickSort1(nums, 0, nums.size() - 1);
//	Print(nums);
//	return 0;
//}
//#include <functional>
//#include <algorithm>
//using namespace std;
//
//vector<vector<int>> func(vector<int> nums)
//{
//	    int n = nums.size();
//        sort(nums.begin(), nums.end());
//        vector<int> path;
//        vector<bool> vis(n);
//        vector<vector<int>> ret;
//        std::function<void(int)> dfs = [&](int i){
//            if(i == n)
//            {
//                ret.push_back(path);
//                return;
//            }
//            for (int j = 0; j < n; j++)
//            {
//                if(!vis[j])
//                {
//                    if(j > 0 && nums[j] == nums[j - 1] && vis[j] == false)
//                        continue;
//                    path.push_back(nums[j]);
//                    vis[j] = true;
//                    dfs(i + 1);
//                    vis[j] = false;
//                    path.pop_back();
//                }
//            }
//        };
//        
//        dfs(0);
//        return ret;
//}
//
//int main()
//{
//    vector<int> nums{ 1, 2, 3 };
//    vector<vector<int>> ret = func(nums);
//    return 0;
//}

//int main()
//{
//	std::vector<int> nums{ 1, 2, 2, 3, 3, 1, 2, 2, 3, 3, 3, 1, 2, 2, 3, 8, 18, 23, 42 };
//	QuickSort(nums, 0, nums.size() - 1);
//	Print(nums);
//	return 0;
//}

//struct TreeNode {
//    int val;
//    TreeNode* left;
//    TreeNode* right;
//    TreeNode(int v = 0)
//        :val(v)
//        ,left(nullptr)
//        ,right(nullptr)
//    {}
//};
//
//TreeNode* build(char*& str)
//{
//    if(*str == '#')
//    {
//        str += 2;
//        return nullptr;
//    }
//    else 
//    {
//        int x = 0;
//        while(isdigit(*str))
//        {
//            x = x * 10 + (*str - '0');
//            str++;
//        }
//        str++;
//        TreeNode* head = new TreeNode(x);
//        head->left = build(str);
//        head->right = build(str);
//        return head;
//    }
//    return nullptr;
//}
//TreeNode* Deserialize(char *str) 
//{
//    return build(str);
//    //return nullptr;
//}
//
//
//int main()
//{
//    char s[100] = "1 2 # # 3 6 # # 7 # # ";
//    TreeNode* head = Deserialize(s);
//    return 0;
//}
#include <functional>
#include <type_traits>


template<class T>
struct object_member_function
{};

template<class Ret, class Class, class ...Args>
struct object_member_function<Ret (Class::*)(Args...)>
{
	using ClassType = Class;
};

template<class T>
using object_member_function_t = typename object_member_function<T>::ClassType;

template<class Fn, class ...Args>
auto bindFunction(Fn&& f, Args&& ...args) ->std::function<decltype(f(args...))()>
{
	return std::bind(std::forward<Fn>(f), std::forward<Args>(args)...);
}

template<class Fn, class Class, class ...Args, std::enable_if_t<std::is_same_v<object_member_function_t<Fn>, Class>, int> = 0>
auto bindFunction(Fn&& f, Class&& obj,  Args&& ...args) -> std::function<decltype((std::forward<Class>(obj).*f)(std::forward<Args>(args)...))()>
{
	return [f = std::forward<Fn>(f), obj = std::forward<Class>(obj), ...args = std::forward<Args>(args...)]() {
		return (obj.*f)(args...);
	};
}

template<class Fn, class Class, class ...Args, std::enable_if_t<std::is_same_v<object_member_function_t<Fn>, Class>, int> = 0>
auto bindFunction(Fn&& f, Class* obj,  Args&& ...args) -> std::function<decltype((std::forward<Class>(obj)->*f)(std::forward<Args>(args)...))()>
{
	return [f = std::forward<Fn>(f), obj = std::forward<Class>(obj), ...args = std::forward<Args>(args...)]() {
		return (obj->*f)(args...);
	};
}


int test(int a, int b)
{
	return a + b;
}

class Base
{
public:
	void func1()
	{
		std::cout << "Hello World" << std::endl;
	}
	void func(int a, double d)
	{
		std::cout << "a :" << a << ", d :" << d << std::endl;
	}
};





//int main()
//{
//	std::function<int()> f1 = std::bind(test, 11, 22);
//	std::cout << f1() << std::endl;
//
//	std::function<void()> f2 = std::bind(&Base::func1, Base());
//	std::function<void()> f3 = std::bind(&Base::func, Base(), 11, 12.3);
//	f2();
//	f3();
//
//
//	return 0;
//}


//class MyCircularQueue 
//{
//public:
//    MyCircularQueue(int k) 
//        :_queue(k + 1)
//        ,_capacity(k + 1)
//        , _head(0)
//        , _tail(0)
//    {}
//    
//    bool enQueue(int value) 
//    {
//        if(isFull())
//            return false;
//        _queue[_tail++] = value;
//        _tail %= _capacity;
//        return true;
//    }
//    
//    bool deQueue() 
//    {
//        if(isEmpty())
//            return false;
//        _head++;
//        _head %= _capacity;
//        return true;
//    }
//    
//    int Front() 
//    {
//        if(isFull())
//            return -1;
//        return _queue[_head];
//    }
//    
//    int Rear() 
//    {
//        if(isFull())
//            return -1;
//        return _queue[(_tail - 1 + _capacity) % _capacity];
//    }
//    
//    bool isEmpty() 
//    {
//        return _head == _tail;     
//    }
//    
//    bool isFull() 
//    {
//        return (_tail + 1) % _capacity == _head;    
//    }
//private:
//    std::vector<int> _queue;
//    int _capacity;
//    int _head, _tail;
//};
//
//
//int main()
//{
//    MyCircularQueue* q = new MyCircularQueue(3);
//    std::cout << q->enQueue(1) << std::endl;
//    std::cout << q->enQueue(2) << std::endl;
//    std::cout << q->enQueue(3) << std::endl;
//    std::cout << q->enQueue(4) << std::endl;
//    std::cout << q->Rear() << std::endl;
//    std::cout << q->isFull() << std::endl;
//    std::cout << q->deQueue() << std::endl;
//    std::cout << q->enQueue(4) << std::endl;
//    std::cout << q->Rear();
//    return 0;
//}



